<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>简化版v3响应式原理</title>
  </head>
  <body>
    <script>
        // 响应式原理："Vue 的响应式原理是通过 数据劫持 + 依赖收集 + 派发更新 实现的。Vue2 使用 Object.defineProperty 递归劫持对象属性，Vue3 改用 Proxy 代理整个对象，配合 Reflect 实现更强大的响应式能力。当数据变化时，通过 依赖跟踪系统 自动触发关联的视图更新。"
      // 存储依赖关系的全局容器
      const targetMap = new WeakMap();

      // 当前正在执行的 effect
      let activeEffect = null;

      // 响应式核心实现
      function reactive(target) {
        // 只处理对象类型
        if (!isObject(target)) return target;

        // 避免重复代理
        if (target.__v_reactive) return target.__v_reactive;

        // 创建代理对象
        const proxy = new Proxy(target, {
          get(target, key, receiver) {
            // 追踪依赖
            track(target, key);

            // 处理特殊属性
            if (key === "__v_reactive") return true;
            if (key === "__v_raw") return target;

            // 递归处理嵌套对象
            const res = Reflect.get(target, key, receiver);
            return isObject(res) ? reactive(res) : res;
          },

          set(target, key, value, receiver) {
            // 获取旧值用于比较
            const oldValue = Reflect.get(target, key, receiver);

            // 执行默认行为
            const result = Reflect.set(target, key, value, receiver);

            // 只有值变化时才触发更新
            if (!Object.is(oldValue, value)) {
              trigger(target, key);
            }

            return result;
          },

          has(target, key) {
            track(target, key);
            return Reflect.has(target, key);
          },

          deleteProperty(target, key) {
            const hadKey = Reflect.has(target, key);
            const result = Reflect.deleteProperty(target, key);
            if (hadKey && result) {
              trigger(target, key);
            }
            return result;
          },

          ownKeys(target) {
            track(target, "ITERATE_KEY");
            return Reflect.ownKeys(target);
          },
        });

        // 标记已代理
        target.__v_reactive = proxy;
        return proxy;
      }

      // ref 实现
      function ref(value) {
        return {
          __v_isRef: true,
          get value() {
            track(this, "value");
            return value;
          },
          set value(newVal) {
            if (Object.is(value, newVal)) return;
            value = newVal;
            trigger(this, "value");
          },
        };
      }

      // effect 实现
      function effect(fn, options = {}) {
        const effectFn = () => {
          try {
            activeEffect = effectFn;
            return fn();
          } finally {
            activeEffect = null;
          }
        };

        // 配置项处理
        effectFn.options = options;
        effectFn.deps = [];

        // 立即执行
        if (!options.lazy) {
          effectFn();
        }

        return effectFn;
      }

      // 依赖追踪
      function track(target, key) {
        if (!activeEffect) return;

        let depsMap = targetMap.get(target);
        if (!depsMap) {
          depsMap = new Map();
          targetMap.set(target, depsMap);
        }

        let deps = depsMap.get(key);
        if (!deps) {
          deps = new Set();
          depsMap.set(key, deps);
        }

        deps.add(activeEffect);
        activeEffect.deps.push(deps);
      }

      // 触发更新
      function trigger(target, key) {
        const depsMap = targetMap.get(target);
        if (!depsMap) return;

        // 普通属性更新
        const effects = new Set();
        const addEffects = (deps) => {
          deps &&
            deps.forEach((effect) => {
              effects.add(effect);
            });
        };

        addEffects(depsMap.get(key));

        // 处理数组 length 变化
        if (Array.isArray(target) && key === "length") {
          depsMap.forEach((dep, key) => {
            if (key >= target.length) addEffects(dep);
          });
        }

        // 执行 effects
        effects.forEach((effect) => {
          if (effect.options.scheduler) {
            effect.options.scheduler(effect);
          } else {
            effect();
          }
        });
      }

      // 工具函数
      function isObject(val) {
        return val !== null && typeof val === "object";
      }

      // 使用示例
      const state = reactive({
        count: 0,
        list: [1, 2, 3],
        nested: {
          prop: "hello",
        },
      });

      effect(() => {
        console.log("count changed:", state.count);
      });

      effect(() => {
        console.log("list changed:", state.list.join(","));
      });

      state.count++; // 触发第一个 effect
      state.list.push(4); // 触发第二个 effect
      state.nested.prop = "world"; // 触发嵌套对象更新
    </script>
  </body>
</html>
